package com.bzkj.basicinfo.service.impl.warehouse;

import com.bzkj.basicinfo.config.YiLianYunMaConfig;
import com.bzkj.basicinfo.domain.warehouse.BarRelation;
import com.bzkj.basicinfo.domain.warehouse.PdaBillsList;
import com.bzkj.basicinfo.domain.warehouse.PdaMsfxBardata;
import com.bzkj.basicinfo.domain.warehouse.PdaWarehouseBillsDetail;
import com.bzkj.basicinfo.domain.warehouse.dto.YiLianYunMaDeliveryRequest;
import com.bzkj.basicinfo.domain.warehouse.dto.YiLianYunMaResponse;
import com.bzkj.basicinfo.domain.warehouse.dto.YiLianYunMaTokenRequest;
import com.bzkj.basicinfo.domain.warehouse.dto.YiLianYunMaTokenResponse;
import com.bzkj.basicinfo.mapper.BarRelationMapper;
import com.bzkj.basicinfo.mapper.PdaMsfxBardataMapper;
import com.bzkj.basicinfo.service.warehouse.IYiLianYunMaService;
import com.bzkj.common.utils.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 易联云码平台对接Service业务层处理
 * 
 * @author lixinyu
 * @date 2025-01-20
 */
@Service
public class YiLianYunMaServiceImpl implements IYiLianYunMaService
{
    private static final Logger log = LoggerFactory.getLogger(YiLianYunMaServiceImpl.class);

    @Autowired
    private YiLianYunMaConfig yiLianYunMaConfig;

    @Resource
    private RestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    @Resource
    private PdaMsfxBardataMapper pdaMsfxBardataMapper;

    @Resource
    private BarRelationMapper barRelationMapper;

    /**
     * 获取易联云码平台Token
     */
    @Override
    public String getToken() throws Exception
    {
        String url = yiLianYunMaConfig.getBaseUrl() + yiLianYunMaConfig.getTokenUrl();
        
        YiLianYunMaTokenRequest request = new YiLianYunMaTokenRequest(
            yiLianYunMaConfig.getUsername(), 
            yiLianYunMaConfig.getPassword()
        );

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<YiLianYunMaTokenRequest> entity = new HttpEntity<>(request, headers);

        log.info("获取易联云码平台Token，请求URL: {}", url);
        log.info("请求参数: {}", objectMapper.writeValueAsString(request));

        ResponseEntity<YiLianYunMaTokenResponse> response = restTemplate.exchange(
            url, HttpMethod.POST, entity, YiLianYunMaTokenResponse.class
        );

        YiLianYunMaTokenResponse tokenResponse = response.getBody();
        log.info("获取Token响应: {}", objectMapper.writeValueAsString(tokenResponse));

        if (tokenResponse == null || !"200".equals(tokenResponse.getCode()))
        {
            String errorMsg = tokenResponse != null ? tokenResponse.getMsg() : "获取Token失败";
            log.error("获取易联云码平台Token失败: {}", errorMsg);
            throw new Exception("获取易联云码平台Token失败: " + errorMsg);
        }

        return tokenResponse.getToken();
    }

    /**
     * 上传单据到易联云码平台
     */
    @Override
    public YiLianYunMaResponse uploadBills(PdaBillsList pdaBillsList) throws Exception
    {
        String token = getToken();
        return uploadBillsWithToken(pdaBillsList, token);
    }

    /**
     * 上传单据到易联云码平台（带Token）
     */
    @Override
    public YiLianYunMaResponse uploadBillsWithToken(PdaBillsList pdaBillsList, String token) throws Exception
    {
        String url = yiLianYunMaConfig.getBaseUrl() + yiLianYunMaConfig.getDeliveryUrl();
        
        // 构建请求数据
        YiLianYunMaDeliveryRequest request = buildDeliveryRequest(pdaBillsList);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + token);

        HttpEntity<YiLianYunMaDeliveryRequest> entity = new HttpEntity<>(request, headers);

        log.info("上传单据到易联云码平台，请求URL: {}", url);
        log.info("请求参数: {}", objectMapper.writeValueAsString(request));

        ResponseEntity<YiLianYunMaResponse> response = restTemplate.exchange(
            url, HttpMethod.POST, entity, YiLianYunMaResponse.class
        );

        YiLianYunMaResponse uploadResponse = response.getBody();
        log.info("上传单据响应: {}", objectMapper.writeValueAsString(uploadResponse));

        return uploadResponse;
    }

    /**
     * 构建配送请求数据
     */
    private YiLianYunMaDeliveryRequest buildDeliveryRequest(PdaBillsList pdaBillsList)
    {
        YiLianYunMaDeliveryRequest request = new YiLianYunMaDeliveryRequest();

        // 设置基本信息
        request.setBillNo(StringUtils.isNotEmpty(pdaBillsList.getBillsID()) ? pdaBillsList.getBillsID() : "");

        request.setHospCode(StringUtils.isNotEmpty(pdaBillsList.getInstitutionId()) ? pdaBillsList.getInstitutionId() : "");
        request.setThisEntName(StringUtils.isNotEmpty(pdaBillsList.getInstitutionName()) ? pdaBillsList.getInstitutionName() : "");
        request.setCreateUser(pdaBillsList.getUserID());


        request.setFromEntName(yiLianYunMaConfig.getFromEntName());
        request.setFromCreditCode(yiLianYunMaConfig.getFromCreditCode());

        // 处理明细数据
        List<PdaWarehouseBillsDetail> detailList = pdaBillsList.getPdaWarehouseBillsDetailList();
        if (detailList != null && !detailList.isEmpty())
        {
            // 取第一条明细作为主要信息
            PdaWarehouseBillsDetail firstDetail = detailList.get(0);

            request.setGoodsName(StringUtils.isNotEmpty(firstDetail.getDrugName()) ? firstDetail.getDrugName() : "");
            request.setSpec(StringUtils.isNotEmpty(firstDetail.getDrugGG()) ? firstDetail.getDrugGG() : "");
            request.setCompanySc(StringUtils.isNotEmpty(firstDetail.getDrugCD()) ? firstDetail.getDrugCD() : "");
            request.setBatchNo(StringUtils.isNotEmpty(firstDetail.getDrugBatchNo()) ? firstDetail.getDrugBatchNo() : "");
            request.setEffectDate(StringUtils.isNotEmpty(firstDetail.getDrugExp()) ? firstDetail.getDrugExp() : "");

            // 查询追溯码
            String traceCode = getTraceCodeByDetails(detailList,pdaBillsList);
            request.setTraceCode(traceCode);
        }

        return request;
    }

    /**
     * 根据单据明细获取追溯码
     * 通过DrugID关联查询PDA_Msfx_BarData_Local表，递归查询到所有一级码
     */
    private String getTraceCodeByDetails(List<PdaWarehouseBillsDetail> detailList,PdaBillsList pdaBillsList)
    {
        try
        {
            // 收集所有药品ID
            List<String> drugIDs = detailList.stream()
                .map(PdaWarehouseBillsDetail::getDrugID)
                .filter(StringUtils::isNotEmpty)
                .distinct()
                .collect(Collectors.toList());

            if (drugIDs.isEmpty())
            {
                log.warn("单据明细中没有有效的药品ID");
                return "";
            }

            log.info("开始获取追溯码，药品ID数量: {}", drugIDs.size());

            // 为每个药品ID获取所有追溯码（包含所有级别的码）
            List<String> allTraceCodes = new ArrayList<>();

            for (String drugID : drugIDs)
            {
                List<String> drugTraceCodes = getAllTraceCodesByDrugID(drugID,pdaBillsList);
                allTraceCodes.addAll(drugTraceCodes);
            }

            if (allTraceCodes.isEmpty())
            {
                log.warn("未找到对应的追溯码，药品ID: {}", drugIDs);
                return "";
            }

            // 去重并拼接所有追溯码
            String traceCode = allTraceCodes.stream()
                .distinct()
                .collect(Collectors.joining(","));

            log.info("获取到追溯码总数: {}，拼接结果长度: {}", allTraceCodes.size(), traceCode.length());
            return traceCode;
        }
        catch (Exception e)
        {
            log.error("获取追溯码失败", e);
            return "";
        }
    }

    /**
     * 获取单个药品的所有追溯码（包含所有级别的码）
     */
    private List<String> getAllTraceCodesByDrugID(String drugID,PdaBillsList pdaBillsList)
    {
        try
        {
            log.info("开始查询药品所有级别追溯码，药品ID: {}", drugID);

            // 查询该药品的所有级别码
            List<PdaMsfxBardata> allBarcodes = pdaMsfxBardataMapper.selectAllBarcodesByDrugID(drugID,pdaBillsList.getBillsID());

            if (allBarcodes == null || allBarcodes.isEmpty())
            {
                log.warn("未找到药品的追溯码，药品ID: {}", drugID);
                return new ArrayList<>();
            }

            // 收集所有级别的追溯码
            List<String> allTraceCodes = collectAllLevelTraceCodes(allBarcodes);

            log.info("药品 {} 查询完成，获得所有级别追溯码数量: {}", drugID, allTraceCodes.size());
            return allTraceCodes;
        }
        catch (Exception e)
        {
            log.error("查询药品所有级别追溯码失败，药品ID: {}", drugID, e);
            return new ArrayList<>();
        }
    }

    /**
     * 收集所有级别的追溯码（包括原始码和递归查询到的所有子码）
     */
    private List<String> collectAllLevelTraceCodes(List<PdaMsfxBardata> allBarcodes)
    {
        List<String> allTraceCodes = new ArrayList<>();

        // 首先添加原始的所有级别码
        List<String> originalCodes = allBarcodes.stream()
            .map(PdaMsfxBardata::getBarcode)
            .filter(StringUtils::isNotEmpty)
            .collect(Collectors.toList());
        allTraceCodes.addAll(originalCodes);

        log.info("添加原始码数量: {}", originalCodes.size());

        // 按级别分组
        Map<Integer, List<PdaMsfxBardata>> levelGroups = allBarcodes.stream()
            .collect(Collectors.groupingBy(PdaMsfxBardata::getCodelevel));

        // 对于每个级别大于1的码，递归查询其所有子码
        for (Map.Entry<Integer, List<PdaMsfxBardata>> entry : levelGroups.entrySet())
        {
            Integer level = entry.getKey();
            List<PdaMsfxBardata> codes = entry.getValue();

            if (level > 1)
            {
                log.info("处理{}级码，数量: {}，开始递归查询所有子码", level, codes.size());
                List<String> subCodes = getAllSubCodesRecursively(codes);
                allTraceCodes.addAll(subCodes);
            }
        }

        return allTraceCodes;
    }

    /**
     * 递归查询所有子码（包含所有级别）
     */
    private List<String> getAllSubCodesRecursively(List<PdaMsfxBardata> parentCodes)
    {
        List<String> allResults = new ArrayList<>();

        // 获取父级码列表
        List<String> parentCodeStrings = parentCodes.stream()
            .map(PdaMsfxBardata::getBarcode)
            .filter(StringUtils::isNotEmpty)
            .collect(Collectors.toList());

        if (parentCodeStrings.isEmpty())
        {
            return allResults;
        }

        try
        {
            log.info("递归查询所有子码，父级码数量: {}, 级别: {}", parentCodeStrings.size(),
                parentCodes.isEmpty() ? "未知" : parentCodes.get(0).getCodelevel());

            // 查询BarRelation表获取子码
            List<BarRelation> barRelations = barRelationMapper.selectCurCodesByParentCodes(parentCodeStrings);

            if (barRelations != null && !barRelations.isEmpty())
            {
                List<PdaMsfxBardata> currentLevelCodes = new ArrayList<>();

                for (BarRelation relation : barRelations)
                {
                    // 为每个子码创建PdaMsfxBardata对象
                    PdaMsfxBardata subCode = new PdaMsfxBardata();
                    subCode.setBarcode(relation.getCurCode());
                    subCode.setCodelevel(Integer.parseInt(relation.getCodeLevel()));
                    subCode.setScantime(relation.getScanTime());
                    subCode.setBarstate("0");
                    subCode.setOrderstate("0");

                    currentLevelCodes.add(subCode);

                    // 添加当前级别的码到结果中
                    allResults.add(relation.getCurCode());
                }

                log.info("当前级别查询到子码数量: {}", currentLevelCodes.size());

                // 按级别分组
                Map<Integer, List<PdaMsfxBardata>> levelGroups = currentLevelCodes.stream()
                    .collect(Collectors.groupingBy(PdaMsfxBardata::getCodelevel));

                // 对于所有非一级码，继续递归查询
                for (Map.Entry<Integer, List<PdaMsfxBardata>> entry : levelGroups.entrySet())
                {
                    Integer level = entry.getKey();
                    List<PdaMsfxBardata> codes = entry.getValue();

                    if (level > 1)
                    {
                        log.info("发现{}级码，数量: {}，继续递归查询", level, codes.size());
                        List<String> subResults = getAllSubCodesRecursively(codes);
                        allResults.addAll(subResults);
                    }
                }
            }
            else
            {
                log.warn("在BarRelation表中未找到对应的子码，父级码: {}", parentCodeStrings);
            }
        }
        catch (Exception e)
        {
            log.error("递归查询所有子码失败，父级码: {}", parentCodeStrings, e);
        }

        return allResults;
    }


}
